#include <stdio.h>
#include "mpi.h"

/*************************************************
 * \author James Edmondson
 * \brief Creates a group that is a subset of MPI_COMM_WORLD
 *        and performs a translate ranks from COMM_WORLD to the
 *        new group and vice versa. This test should be ran
 *        with more than 3 processes.
 *************************************************/

int
main(int argc, char **argv)
{
	int size, rank, i, newgroup_size, excluded;
	MPI_Group worldgroup, newgroup;
	int * ranks1, * ranks2, * ranks3;

	MPI_Init(&argc, &argv);
	
	MPI_Comm_size(MPI_COMM_WORLD, &size);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);

	if( size < 3 )
	{
		fprintf(stderr,"Error: This test requires at least 3 processes.\n");
		exit(1);
	}
	
	ranks1 = (int *)malloc(sizeof(int) * size);
	ranks2 = (int *)malloc(sizeof(int) * size);
	ranks3 = (int *)malloc(sizeof(int) * size);
	
	MPI_Comm_group(MPI_COMM_WORLD, &worldgroup);

	/* fill the ranks1 array with every rank in MPI_COMM_WORLD
	 * this is used by the translate ranks function */
	
	for( i = 0; i < size; i++ )
	{
		ranks1[i] = i;
	}

	/* fill the ranks2 array (temporarily) with ranks that will
	 * be excluded from the newly created group. We want to exclude
	 * the first, middle, and last rank */

	ranks2[0] = 0;
	ranks2[1] = size / 2;
	ranks2[2] = size - 1;
	
	if ( size > 3 ) excluded = 3;
	else excluded = 1;
	
	MPI_Group_excl(worldgroup, excluded, ranks2, &newgroup);
	MPI_Group_size(newgroup,&newgroup_size);
	
	MPI_Group_translate_ranks(worldgroup,size,ranks1,newgroup,ranks2);
//	MPI_Group_translate_ranks(newgroup,size,ranks1,newgroup,ranks3);

	if( rank == 0 )
	{
		printf("COMM_WORLD = ");
		for( i = 0; i < size; i++ )
		{
			printf("%d ",i);
		}
		printf("\nNEW_GROUP has %d processes.\n",newgroup_size);
		printf("\nTranslation from rank in COMM_WORLD to NEW_GROUP\n");
		printf("COMM_WORLD\t-->\tNEW_GROUP\n");
		for( i = 0; i < size; i++ )
		{
			printf("%d\t-->\t%d\n",i,ranks2[i]);
		}

		if( excluded == 3 )
		{
			if( ranks2[0] < 0 && ranks2[size/2] < 0 && ranks2[size-1] < 0 )
			{
				printf("SUCCESS.\n"); 
			}
			else
			{
				printf("FAILURE.\n");
			}
		}
		else if( excluded == 1 )
		{
			if( ranks2[0] < 0 )
			{
				printf("SUCCESS.\n");
			}
			else
			{
				printf("FAILURE.\n");
			}
		}
	}
	
	MPI_Finalize();
	return 0;
}

